// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of dart.core;

/**
 * [Expando]允许向对象添加新的属性。
 *
 * 属性不支持number，string，bool类型和null。
 *
 * 当一个对象变得无法访问时，`Expando`不会继续控制被添加的属性值。
 *
 * 你总是可以创建一个新的number，它和已经存在的number完全相同。
 * 这意味着，在number上的一个expando属性永远不可能被释放。
 * 为避免这种情况，expando属性不能被添加到number中。
 * 同样的情况也适用于string，bool和null，也包括字面量
 * （因为在它们出现多次时，计算的值完全相同）。
 *
 * 对于其它的类没有任何限制，即使对象是编译时常量。
 * 请注意，如果将expando属性添加到编译时常量中，必须在它们可以更新的时候。
 *
 * 通常情况下，Expando适用于Web应用。
 * 下面是命令行的简单例子，将一个对于与另一个对象关联，功能类似于`Map`：
 *     typedef CustomFunction(int foo, String bar);
 *
 *     Expando<CustomFunction> domFunctionExpando = new Expando<CustomFunction>();
 *
 *     main(){
 *       // 通常情况下，new的是Element
 *       final myElement = new Object();
 *
 *       // 在DOM element上使用expando
 *       domFunctionExpando[myElement] = someFunc;
 *
 *       // 现在，已经将函数附到对象后面
 *       // 接着可以调用函数：
 *       domFunctionExpando[myElement](42, 'expandos are cool');
 *     }
 *
 *     void someFunc(int foo, String bar){
 *       print('Hello. $foo $bar');
 *     }
 */
class Expando<T> {

  /**
   * 传入构造函数的[Expando]的名称。
   * 如果没有传递名称给构造函数，name为[:null:]。
   */
  final String name;

  /**
   * 创建一个新的[Expando]。
   * 可选参数name的目的是仅用作调试，
   * 或使用相同的name创建两个不同的[Expando]，便于区分它们使用对象的不同属性。
   */
  external Expando([String name]);

  /**
   * 重写toString方法。
   */
  String toString() => "Expando:$name";

  /**
   * 通过object获取[Expando]属性的值。如果对象还没有被扩展，方法返回[:null:]。
   *
   * object不能是number，string，bool或者null。
   */
  external T operator [](Object object);

  /**
   * 设置[Expando]的属性为object，关联的值为value。
   * 当设置属性的值为`null`时，属性又会被有效地删除。
   *
   * object不能是number，string，bool或者null。
   */
  external void operator []=(Object object, T value);

}
